import { createHashHistory } from "history";
// import StateApi from "./StateApi";
const _history = createHashHistory();
console.log(_history);
/**
 * 格式化日期
 * @param {string} str [description]
 * example
   new Date().zenFormat('Y-m-d');
 */
window.Date.prototype.ZenFormat = function(str) {
    var _self = this;
    var resultStr;
    var matchObj = {
        Y: _self.getFullYear(),
        m: addZeroWhenNotEnough(_self.getMonth() + 1, 10),
        d: addZeroWhenNotEnough(_self.getDate(), 10),
        H: addZeroWhenNotEnough(_self.getHours(), 10),
        i: addZeroWhenNotEnough(_self.getMinutes(), 10),
        s: addZeroWhenNotEnough(_self.getSeconds(), 10)
    };
    function addZeroWhenNotEnough(rawValue, count) {
        if (rawValue < count) {
            rawValue = "0" + rawValue;
        }
        return rawValue;
    }
    for (var attr in matchObj) {
        str = str.replace(attr, matchObj[attr]);
    }
    return str;
};

Date.prototype.addDay = function(count, format) {
    if (!count) {
        return;
    }
    var oneDaySecond = 3600 * 24 * 1000 * count;
    return new Date(this.getTime() + oneDaySecond);
};

Date.prototype.minusDay = function(count) {
    if (!count) {
        return;
    }
    var timestamp = this.setDate(this.getDate() - count);
    return new Date(timestamp);
};

/**
 * 通用工具方法
 * @namespace Uts
 */
let Uts = {
    /**
     * console.log one error
     * params   text:text to console output
     * @return   {type}
     */
    ce(text) {
        global.console.error && global.console.error(text);
    },
    /**
     * set class
     * @param  {array} options  the expression to set class
     * @return {string}         the className result
     * @example
     Uts.sc([
         formData.$$status.test1 ? "a" : "b",
         "hello world"
     ])
     */
    sc(arr) {
        if (this.notEmptyArray(arr)) {
            return arr.join(" ");
        }
    },
    /**
     * throw one error
     * @param  {string} text [description]
     * @return {type}      [description]
     */
    te(text) {
        throw new Error(text);
    },
    isTrue(value) {
        return Boolean(value);
    },
    /**
     * navigage to new path
     * @param  {string} path  the path to navigage
     * @return {string}         
     * @example
     const path = `/repos/${userName}/${repo}`;
     $stateGo(path);
     */
    $stateTo(path) {
        //<Redirect to="/somewhere/else" />
        /*
        <Redirect
          to={{
            pathname: "/login",
            search: "?utm=your+face",
            state: { referrer: currentLocation }
          }}
        />
         */
        // $state;
        // const path = `/repos/${userName}/${repo}`
        // browserHistory.push(path);
        //return <Redirect to={path} />;
        _history.push(path);
    },
    /**
     * navigage to new path
     * @param  {string} path  the path to navigage
     * @return {string}         
     * @example
     const path = `/repos/${userName}/${repo}`;
     $stateGo(path);
     */
    $stateGo(options) {
        let routerObject = {
            pathname: options.stateName || options.name, //"/login",
            search: Uts.paramsToSearch(options.params), //"?utm=your+face",
            state: options.state
        };
        //<Redirect to="/somewhere/else" />
        /*
        <Redirect
          to={{
            pathname: "/login",
            search: "?utm=your+face",
            state: { referrer: currentLocation }
          }}
        />
         */
        // const path = `/repos/${userName}/${repo}`
        if (options.reload) {
            routerObject = routerObject.pathname + routerObject.search;
        }
        _history.push(routerObject);
    },
    /**
     * loop for array
     * @param  {type}   arr [description]
     * @param  {Function} cb  [description]
     * @return {type}       [description]
     *@example
     each(array,function(item,index){});
     */
    each(arr, cb) {
        if (this.isArray(arr) && cb) {
            for (var i = 0; i < arr.length; i++) {
                if (this.pauseEach) {
                    break;
                }
                cb && cb(arr[i], i);
            }
            delete this.pauseEach;
        }
    },
    paramsToSearch(param, key, encode, ifDeepMode, firstTime) {
        if (param == null) return "";
        var paramStr = "";
        var t = typeof param;
        if (ifDeepMode) {
            var encodeStr = this.copyObj(param);
            if (Uts.isObject(encodeStr)) {
                encodeStr = Uts.toStr(encodeStr);
            }
            if (!this.ifHadEncode(encodeStr)) {
                encodeStr = encodeURIComponent(encodeStr);
            }
            var flagSymbol = firstTime ? "?" : "&";
            paramStr +=
                flagSymbol +
                key +
                "=" +
                (encode == null || encode ? encodeStr : param);
        } else {
            var firstTime = true;
            for (var i in param) {
                var k =
                    key == null
                        ? i
                        : key +
                          (param instanceof Array ? "[" + i + "]" : "." + i);
                paramStr += Uts.paramsToSearch(
                    param[i],
                    k,
                    encode,
                    true,
                    firstTime
                );
                firstTime = false;
            }
        }
        return paramStr;
    },
    notEmptyString(string) {
        return string && this.isString(string);
    },
    notEmptyArray(arr) {
        return arr.length && this.isArray(arr);
    },
    mergeArray(rawArr, valueArray) {
        if (this.isArray(rawArr) & this.notEmptyArray(valueArray)) {
            Array.prototype.push.apply(rawArr, valueArray);
        }
    },
    /**
     * get cookie by name
     * @param  {string} cookie name [description]
     * @return {string} cookie value           [description]
     */
    getCookie(cookieName) {
        var name = cookieName + "=";
        var ca = document.cookie.split(";");
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == " ") {
                c = c.substring(1);
            }
            if (c.indexOf(name) == 0) {
                return Uts.decode(c.substring(name.length, c.length));
            }
        }
        return "";
    },
    /**
     * setCookie by name and value
     * @param {string} cname   [description]
     * @param {string} cvalue  [description]
     * @param {string} domaine [description]
     */
    setCookie(cname, cvalue, options = {}) {
        if (Uts.isUndefined(cvalue)) {
            return false;
        }
        var d = new Date();
        options.path = "/";
        var h = location.hostname;
        options.domain =
            h.indexOf("localhost") < 0 &&
            !/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(
                h
            )
                ? h.substring(h.indexOf("."), h.length)
                : location.hostname;
        options.expires = options.expires || 0.08;
        if (typeof options.expires === "number") {
            var days = options.expires,
                t = (options.expires = new Date());
            t.setTime(+t + days * 864e5);
        }
        // d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
        // var expires = "expires="+d.toUTCString();
        document.cookie =
            cname +
            "=" +
            Uts.encode(cvalue) +
            ";path=" +
            options.path +
            (options.domain ? "; domain=" + options.domain : "") +
            (options.expires
                ? "; expires=" + options.expires.toUTCString()
                : "") +
            (location.protocol.indexOf("https:") > -1 ? "; secure" : "");
    },

    clearAllCookiesAndStorage() {
        var cookieDomain =
            window.location.protocol.indexOf("https:") > -1
                ? { path: "/", secure: true }
                : { path: "/" };
        var h = location.hostname;
        cookieDomain.domain =
            h.indexOf("localhost") < 0 &&
            !/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(
                h
            )
                ? h.substring(h.indexOf("."), h.length)
                : location.hostname;
        cookieDomain.expires = -1;
        let cookiesMap = Uts.cookiesMap();
        let _self = this;

        let secondDomain = Uts.copyObj(cookieDomain);
        secondDomain.domain = location.host;

        Object.keys(cookiesMap).forEach(key => {
            _self.setCookie(key, "", cookieDomain);
            _self.setCookie(key, "", secondDomain);
            _self.setCookie(key, "", { secure: true, expires: -1 });
        });

        localStorage.clear();
        sessionStorage.clear();
        delete cookieDomain.expires;
    },

    decode(s) {
        return decodeURIComponent(s);
    },

    encode(s) {
        return encodeURIComponent(s);
    },

    cookiesMap: function() {
        var cookies = document.cookie ? document.cookie.split("; ") : [];
        var result = {};
        for (var i = 0, l = cookies.length; i < l; i++) {
            var parts = cookies[i].split("=");
            var name = Uts.decode(parts.shift());
            var cookie = parts.join("=");
            result[name] = cookie;
        }

        return result;
    },
    /**
     * setCookieMt description
     * @example
     setCookieMt({name:value,name2:value});
     */
    setCookieMt(options) {
        for (var pop in options) {
            Uts.setCookie(pop, options[pop]);
        }
    },
    /**
     * getEnv 
     * @param  {string} [string] [description]
     * @return {object}        [description]
     * @example
     Uts.getEnv();
     Uts.getEnv('www.demo.rjmart.cn')
     //return example
     {
       "rootDomain": "rjmart.cn",
       "env": "demo"
     }
     */
    getEnv(string) {
        let config = {};
        let host = string || location.host;
        config.rootDomain =
            (host.match(Uts.FINDDOMAINEXP) &&
                host.match(Uts.FINDDOMAINEXP)[0]) ||
            null;
        config.env = "";
        switch (true) {
            case Uts.contain(host, "localhost:"):
                config.env = "localhost";
                config.rootDomain = "localhost";
                break;
            //"www.gray.rjmart.cn"
            case Uts.contain(host, "gray"):
                config.env = "gray";
                break;
            //www.rjmart.rj-info.com
            case Uts.contain(host, "rjmart.rj-info"):
                config.env = "uat";
                break;
            //test4.rj-info.com
            case Uts.contain(host, "test4"):
                config.env = "test4";
                break;
            //www.demo.rjmart.cn
            case Uts.contain(host, "demo"):
                config.env = "demo";
                break;
            //www.rjmart.cn
            case Uts.contain(host, "www.rjmart.cn"):
                config.env = "publish";
                break;

            default:
        }

        return config;
    },
    min(x, y) {
        return Math.min(x, y);
    },
    transferReg(value) {
        if (value) {
            return value.replace(/([\$\(\)\*\+\.\[\]\?\\\^\{\}\|])/g, "\\$1");
        }
        return value;
    },
    /**
     * findObjByCondition in array
     * @param  {array}  arr      [description]
     * @param  {object}  cond     [description]
     * @param  {Boolean} isStrict [description]
     * @return {array}           [description]
     * @example
     //return [{a:1,b:2,c:3},{a:1,c:3}] 
     Uts.findObjByCondition([{a:1},{a:1,b:2,c:3},{a:1,c:3}],{a:1,c:3})
     //return [{a:1,c:3}]
     Uts.findObjByCondition([{a:1},{a:1,b:2,c:3},{a:1,c:3}],{a:1,c:3},true)
     */
    findObjByCondition(arr, cond, isStrictMode, returnIndex) {
        if (this.notEmptyArray(arr)) {
            let _self = this;
            let result = [];
            let keys = Object.getOwnPropertyNames(cond);
            _self.each(arr, function(item, index) {
                let isMatch = true;
                let matchIndex;
                if (
                    !isStrictMode ||
                    (isStrictMode &&
                        Object.getOwnPropertyNames(item).length == keys.length)
                ) {
                    _self.each(keys, function(keysItem, keysIndex) {
                        if (item[keysItem] != cond[keysItem]) {
                            isMatch = false;
                        }
                    });
                    if (isMatch) {
                        result.push(returnIndex ? index : item);
                        if (isStrictMode) {
                            _self.pauseEach = true;
                        }
                    }
                }
            });
            return result;
        }
    },
    filterObjByCondition(arr, cond, isStrictMode) {
        let findResult = Uts.findObjByCondition(arr, cond, isStrictMode);
        return findResult;
    },
    /**
     * getObjectKeys
     * @param  {object} obj [description]
     * @return {array}     [description]
     */
    getObjectKeys(obj) {
        if (this.isObject(obj)) {
            return Object.getOwnPropertyNames(obj);
        }
    },
    /**
     * format string to Json
     * @param  {string} value the string to format to Json
     * @return {object}       the json object result
     */
    toJSON(value) {
        if (this.notEmptyString(value)) {
            return JSON.parse(value);
        } else if (this.isObject(value)) {
            return value;
        } else {
            return null;
        }
    },
    toStr(obj) {
        if (this.isObject(obj)) {
            return JSON.stringify(obj);
        }
        return obj;
    },
    E(exp, parentElement = document) {
        return parentElement.querySelector(exp);
    },
    /**
     * @namespace storage
     */
    storage: {
        /**
         * Uts.storage.get(name);
         * @param  {string} name ,the storage name
         * @return {object}      the storage object
         */
        get: function(name) {
            let value = localStorage.getItem(name);
            try {
                value = Uts.toJSON(value);
            } catch (err) {}
            return value;
        },
        /**
         * Uts.storage.set(name,value);
         * @param {name} name  the storage name
         * @param {object} value  ,the storage object
         */
        set: function(name, value) {
            if (Uts.isDefined(value)) {
                if (Uts.isObject(value)) {
                    value = Uts.toStr(value);
                }
                localStorage.setItem(name, value);
            }
        }
    },
    /**
     * addScript description
     * @param {string} t script path
     * @param {function} e callback run after script load
     */
    addScript(t, e) {
        var n = Uts.createDom("script");
        (n.src = t),
            (n.anysc = !0),
            null == n.onload
                ? (n.onload = function() {
                      "function" == typeof e && e();
                  })
                : (n.onreadystatechange = function() {
                      ("loaded" != n.readyState &&
                          "complete" != n.readyState) ||
                          ("function" == typeof e && e());
                  }),
            Uts.addDom("append", document.getElementsByTagName("body")[0], n);
        // document.getElementsByTagName("body")[0].appendChild(n);
    },
    /**
     * addDom /before/after/prepend/append/replace/
     * @param {string} type          /before/after/prepend/append/replace/
     * @param {object} parentElement the elment to count positin
     * @param {object} element       [description]
     * @param {null} newElement    [description]
     */
    addDom(type, parentElement, element, newElement) {
        switch (type) {
            case "before":
                //parentElement is the element count position
                parentElement.parentNode.insertBefore(element, parentElement);
                break;
            case "after":
                //parentElement is the element count position
                parentElement.parentNode.insertBefore(
                    element,
                    parentElement.nextSibling
                );
                break;
            case "prepend":
                let preFirstChild = parentElement.childNodes[0];
                parentElement.insertBefore(element, preFirstChild);
                break;
            case "append":
                parentElement.appendChild(element);
                break;
            case "replace":
                if (newElement) {
                    parentElement.replaceChild(newElement, element);
                }
                break;
            default:
        }
    },
    /**
     * removeDom
     * @param  {object} element [description]
     * @return {null}         [description]
     */
    removeDom(element) {
        // parentElement.removeChild(element);
        element.parentNode.removeChild(element);
    },
    /**
     * check if element has className
     * @param  {object}  elem      [description]
     * @param  {string}  className [description]
     * @return {Boolean}           [description]
     */
    hasClass(elem, className, isNotStrictMode) {
        if (!elem) {
            return false;
        }
        if (isNotStrictMode) {
            return new RegExp(" " + className.split(" ").join("|") + " ").test(
                " " + elem.className + " "
            );
        }
        let classNameList = className.split(" ");
        let matchResult = true;
        Uts.each(classNameList, function(currentClassName, index) {
            if (
                !new RegExp(" " + className + " ").test(
                    " " + elem.className + " "
                )
            ) {
                matchResult = false;
            }
        });
        return matchResult;
    },
    /**
     * createDom from html
     * @param  {String} html [description]
     * @return {object} dom     [description]
     * @example
      Uts.createDom('div');
      Uts.createDom('<div class="test">abc<span class="test2">xxx</span><em>test</em></div>');
     */
    createDom(html = "") {
        if (!html) {
            return null;
        }
        // html = "<div>test <span>test2</span></div>";
        if (!Uts.contain(html, "<[^>]+>")) {
            return document.createElement(html);
        }
        let tagName = Uts.getTagName(html);
        let tagValue = Uts.getTagValue(html);
        let dom = document.createElement(tagName);
        dom.innerHTML = tagValue;
        return dom;
        // Uts.outTag
    },
    /**
     * getTagName from html
     * @param  {String} html [description]
     * @return {string} tagName     [description]
     * @example
     Uts.getTagName('<div class="test">abc<span class="test2">xxx</span><em>test</em></div>');
     */
    getTagName(html = "") {
        // html = '<div class"test">Test a code</div><em>I am a girl.</em>';
        var result = html.match(Uts.TAGNAMEEXP);
        var tag;
        if (result) {
            tag = result[1];
        }
        return tag;
    },
    getTagValue(html = "") {
        // html ='<div class"test">Test a <span test>xxx</span> code</div><em>I am a girl.</em>';
        let result = "";
        let tagName = Uts.getTagName(html);
        let REGEXP = Uts.TAGVALUEEXP(tagName);
        result = html.replace(REGEXP, "");
        return result;
    },
    allTagEXP: /<[^>]+>/gim,
    TAGNAMEEXP: /<([^\s>]+)(\s|>)+/,
    FINDDOMAINEXP: /[^\.]+\.[^\.]+$/,
    TAGVALUEEXP: function(tagName) {
        return new RegExp(
            "^<" + tagName + "[^>]{0,}>|</" + tagName + ">$",
            "g"
        );
    },
    /**
     * add class to element
     * @param  {object}  elem      [description]
     * @param  {string}  className [description]
     */
    addClass(elem, className) {
        if (!elem) {
            return false;
        }
        let classNameList = className.split(" ");
        Uts.each(classNameList, function(currentClassName, index) {
            if (!Uts.hasClass(elem, currentClassName)) {
                elem.className +=
                    (!elem.className ? "" : " ") + currentClassName;
            }
        });
    },
    /**
     * remove class from element
     * @param  {object}  elem      [description]
     * @param  {string}  className [description]
     */
    removeClass(elem, className) {
        if (!elem) {
            return false;
        }
        if (Uts.hasClass(elem, className, true)) {
            let matchStr = className
                .split(" ")
                .join("\\b|\\b")
                .replace(/ {2,}/g, " ");
            let regExp = new RegExp(" " + matchStr + " ", "g");
            let toCheckClass = " " + elem.className + " ";
            elem.className = toCheckClass
                .replace(regExp, " ")
                .replace(/ {2,}/g, " ")
                .replace(/^ +| +$/g, "");
        }
    },
    /**
     * auto add or remove class for element
     * @param  {object}  elem      [description]
     * @param  {string}  className [description]
     */
    toggleClass(elem, className) {
        if (!elem) {
            return false;
        }
        if (Uts.hasClass(elem, className)) {
            Uts.removeClass(elem, className);
        } else {
            Uts.addClass(elem, className);
        }
    },
    /**
     * notEmptyObject description
     * @param  {object} object [description]
     * @return {boolean}        [description]
     */
    notEmptyObject(object) {
        return Uts.getObjectKeys(object) && Uts.getObjectKeys(object).length;
    },
    autoCleanStateList: ["__modalList", "__testList"],
    cleanState(stateList) {
        /*
        1.check if has that params in autoCleanStateList
        2.if has,delete and replace state
         */
        stateList = stateList || Uts.autoCleanStateList;
        var str = "";
        var currentHash = location.hash;
        var newHash = "";
        Uts.each(stateList, function(item, index) {
            //var USEREGEXP=/&?__modalList=([^&]*)|&?__testList=([^&]*)|&?__modalList$|&?__testList/g
            str +=
                (index > 0 ? "|" : "") +
                "&?" +
                item +
                "=([^&]*)|&?" +
                item +
                "$";
        });
        var USECHECKSTATEREGEXP = new RegExp(str, "g");
        newHash = currentHash.replace(USECHECKSTATEREGEXP, "");
        Uts.repleaceState(null, null, newHash);
    },
    /**
     * getRouterSearch description ,can use for pushState
     * @return {string} [description]
     *
     */
    getRouterSearch(ifReturnParams) {
        var currentHash = location.hash;
        var hashSearch = "";
        var currentParams;
        if (Uts.contain(currentHash, "\\?")) {
            hashSearch = currentHash.substring(currentHash.indexOf("?"));
            currentParams = Uts.getParamsFormSearch(hashSearch);
        }
        return ifReturnParams ? currentParams : hashSearch;
    },
    pushState(options, title, newUrl) {
        history.pushState(null, null, newUrl);
    },
    repleaceState(options, title, newUrl) {
        history.replaceState(null, null, newUrl);
    },
    /**
     * changeState description
     * @param  {string} stateName  [description]
     * @param  {string} stateValue [description]
     * @param  {boolean} isReplaceMode [description]
     * @return {null}            [description]
     *@example
     * Uts.changeState('openModal','test1');
     */
    changeState(stateName, stateValue, isReplaceMode) {
        var currentHash = location.hash;
        var hashSearch;
        var currentParams;
        if (Uts.contain(currentHash, "\\?")) {
            hashSearch = currentHash.substring(currentHash.indexOf("?"));
            currentParams = Uts.getParamsFormSearch(hashSearch);
        }
        var newHash = "";
        if (currentParams && Uts.isDefined(currentParams[stateName])) {
            var oldValue = currentParams[stateName];
            var STATENAMEEXP = new RegExp(stateName + "=([^&]*)");
            newHash = currentHash.replace(
                STATENAMEEXP,
                stateName + "=$1" + (oldValue ? "," : "") + stateValue
            );
        } else {
            newHash =
                location.hash +
                (currentParams ? "&" : "?") +
                stateName +
                "=" +
                stateValue;
        }
        if (isReplaceMode) {
            Uts.repleaceState(null, null, newHash);
        } else {
            Uts.pushState(null, null, newHash);
        }
    },
    /**
     * get element position
     * @param  {object} elem the element to get position
     * @return {object}      {top,right,bottom,left}
     */
    getPS(elem) {
        var scrollx =
                document.documentElement.scrollLeft || document.body.scrollLeft,
            scrollt =
                document.documentElement.scrollTop || document.body.scrollTop;
        var pos = elem.getBoundingClientRect();
        return {
            top: pos.top + scrollt,
            right: pos.right + scrollx,
            bottom: pos.bottom + scrollt,
            left: pos.left + scrollx
        };
    },
    getStyle(elem) {
        return window.getComputedStyle(elem, null);
    },
    initUA() {
        var bodyEle = document.getElementsByTagName("body")[0];
        var browser = {
            versions: (function() {
                var u = navigator.userAgent,
                    app = navigator.appVersion;
                return {
                    trident: u.indexOf("Trident") > -1, //IE内核
                    presto: u.indexOf("Presto") > -1, //opera内核
                    webKit: u.indexOf("AppleWebKit") > -1, //苹果、谷歌内核
                    gecko: u.indexOf("Gecko") > -1 && u.indexOf("KHTML") == -1, //火狐内核
                    mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端
                    ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
                    android: u.indexOf("Android") > -1 || u.indexOf("Adr") > -1, //android终端
                    iphone: u.indexOf("iPhone") > -1, //是否为iPhone或者QQHD浏览器
                    ipad: u.indexOf("iPad") > -1, //是否iPad
                    webapp: u.indexOf("Safari") == -1, //是否web应该程序，没有头部与底部
                    weixin: u.indexOf("MicroMessenger") > -1, //是否微信
                    qq: u.match(/\sQQ/i) == " qq"
                };
            })(),
            language: (
                navigator.browserLanguage || navigator.language
            ).toLowerCase()
        };
        for (var pop in browser.versions) {
            if (browser.versions[pop]) {
                // debugger
                Uts.addClass(bodyEle, "rj_" + pop);
                Uts.UAList = Uts.UAList || {};
                Uts.UAList[pop] = true;
            }
        }
    },
    /**
     * check if is userAgent type
     * @param  {string}  type [description]
     * @return {Boolean}      [description]
     * @example
        Uts.getUA('ios');
     */
    isUA(type) {
        return Uts.UAList[type];
    },
    /**
     * check if value is a function
     * @param  {value}  value to check
     * @return {Boolean}     true or false
     */
    isFunction(obj) {
        return typeof obj === "function";
    },
    /**
     * check a value if had defined
     * @param  {value}  value to check
     * @return {Boolean}     true or false
     */
    isDefined(value) {
        return typeof value !== "undefined";
    },
    /**
     * check a value if undefined
     * @param  {value}  value to check
     * @return {Boolean}     true or false
     */
    isUndefined(value) {
        return typeof value === "undefined";
    },
    /**
     * check value if a object
     * @param  {value}  value to check
     * @return {Boolean}     true or false
     */
    isObject(obj) {
        return typeof obj !== null && typeof obj === "object";
    },
    /**
     * check value if a array
     * @param  {value}  value to check
     * @return {Boolean}     true or false
     */
    isArray(obj) {
        return obj && obj.constructor === Array;
    },
    /**
     * check value if a Number
     * @param  {value}  value to check
     * @return {Boolean}     true or false
     */
    isNumber(value) {
        return typeof value === "number" && !isNaN(value);
    },
    /**
     * check value if a string
     * @param  {value}  value to check
     * @return {Boolean}     true or false
     */
    isString(value) {
        return typeof value === "string";
    },
    /**
     * check value if a Date object
     * @param  {value}  value to check
     * @return {Boolean}     true or false
     */
    isDate(value) {
        return toString.call(value) === "[object Date]";
    },
    /**
     * extend object
     * @param  {object} sourceObj   the object to extend
     * @param  {object} props       the props to extend
     * @return {}                   the object to extend
     */
    extend(sourceObj, props) {
        if (!this.isObject(sourceObj) || !this.isObject(props)) {
            ce("extend need correct params");
            return false;
        }
        for (var pty in props) {
            sourceObj[pty] = props[pty];
        }
    },
    /**
     *contain ,can use for array or string
     *example: 
      contain(someList,someText)
     *@params {source} source the source to check
     *@params {value} value the value to check,could be regExp
     *@example
     Uts.contain('some text fo test','text');
     Uts.contain(['some text fo test','text'],'text');
     Uts.contain(['some text fo test','text'],'[e-m]{3}',1);
     */
    contain(source, value, isContainMode) {
        if (Uts.isUndefined(value)) {
            return false;
        }
        let REGEXP = new RegExp(value);
        if (Uts.isString(source)) {
            return REGEXP.test(source);
        } else if (Uts.isArray(source)) {
            let isMatch = false;
            Uts.each(source, function(value2, index) {
                if (isContainMode) {
                    if (REGEXP.test(value2)) {
                        isMatch = true;
                        Uts.pauseEach = true;
                    }
                } else {
                    let fullMatchREGEXP = new RegExp("^" + value + "$");
                    if (fullMatchREGEXP.test(value2)) {
                        isMatch = true;
                        Uts.pauseEach = true;
                    }
                }
            });
            return isMatch;
        }

        // return source.indexOf(value) > -1;
    },
    /**
     * fetchObjectArrayToStringArray description
     * @param  {array} source    [description]
     * @param  {string} fieldName [description]
     * @return {array}           [description]
     * @example
     //return ['pm1','pm2']
     Uts.fetchObjectArrayToStringArray(
         data.user.permissions,
         "name"
     )
     */
    fetchObjectArrayToStringArray(source, fieldName) {
        let newArray = [];
        Uts.each(source, function(item, index) {
            if (!Uts.contain(newArray, item[fieldName])) {
                newArray.push(item[fieldName]);
            }
        });
        return newArray;
    },
    /**
     * countTotalFromArray description
     * @param  {array} array     [description]
     * @param  {string} fieldName [description]
     * @return {number}           [description]
     */
    countTotalFromArray(array, fieldName) {
        if (Uts.isArray(array)) {
            let totalAmount = 0;
            Uts.each(array, function(value, index) {
                if (Uts.isObject(value) && Uts.isString(fieldName)) {
                    totalAmount += Number(value[fieldName]);
                }
                if (Uts.isString(value)) {
                    totalAmount += Number(value);
                }
            });
            return totalAmount;
        }
    },
    /**
     * hookAjaxHeader description
     * @param  {object} ajaxRes [description]
     * @return {null}         [description]
     * ajaxRes.setRequestHeader(name,value)
     */
    hookAjaxHeader(ajaxRes) {},
    overrideAjax() {
        let _xmlhttp = XMLHttpRequest;
        XMLHttpRequest = function() {
            let ajax = new _xmlhttp();
            ajax._send = ajax.send;
            ajax.send = function(data) {
                // console.log(data);
                if (Uts.isLogin()) {
                    Uts.hookAjaxHeader && Uts.hookAjaxHeader(this);
                    this.setRequestHeader("X-Org", Uts.getCookie("orgId"));
                    if (/^\/shop|^\/suppliers/g.test(this.url)) {
                        if (Uts.getCookie("SPAccrosToken")) {
                            this.setRequestHeader(
                                "Authorization",
                                "Bearer " + Uts.getCookie("SPAccrosToken")
                            );
                        }
                    } else if (/^\/store/g.test(this.url)) {
                        if (Uts.getCookie("accrosToken")) {
                            this.setRequestHeader(
                                "Authorization",
                                "Bearer " + Uts.getCookie("accrosToken")
                            );
                        }
                    } else {
                        if (
                            Uts.getCookie("accrosToken") ||
                            Uts.getCookie("SPAccrosToken")
                        ) {
                            this.setRequestHeader(
                                "Authorization",
                                "Bearer " +
                                    (Uts.getCookie("accrosToken") ||
                                        Uts.getCookie("SPAccrosToken"))
                            );
                        }
                    }
                }
                ajax._send(data);
            };
            ajax._open = ajax.open;
            ajax.open = function(type, url, synType, other) {
                // console.log(type, url, synType, other);
                this.url = url;
                ajax._open(type, url, synType, other);
            };
            // ajax.setRequestHeader("testToken", Uts.getCookie("accrosToken"));
            return ajax;
        };
    },
    /**
     * hash some text
     * @param  {text} code   text to hash
     * @return {text}        hash value
     */
    compressStr(code) {
        var c = String.fromCharCode(code.charCodeAt(0) + code.length);
        for (var i = 1; i < code.length; i++) {
            c += String.fromCharCode(
                code.charCodeAt(i) + code.charCodeAt(i - 1)
            );
        }
        return escape(c);
    },
    /**
     * sort array
     * @params {array} 
     *example 
    options={pty:letter,orderBy:1}//1:ASC,0:DESC
    var testArr=[{a:2},{a:1},{a:3}];
    sort(testArr,options);
    */
    sort(rawArray, options) {
        options = options;
        var orderFlag1, orderFlag2;
        if (options.orderBy === 0) {
            orderFlag1 = -1;
            orderFlag2 = 1;
        } else {
            orderFlag1 = 1;
            orderFlag2 = -1;
        }
        rawArray.sort(function(a, b) {
            return a[options.pty] > b[options.pty] ? orderFlag1 : orderFlag2;
        });
    },

    /**
     * unhash some text
     * @param  {text} code   text to unhash
     * @return {text}        hash value
     */
    unCompressStr(code) {
        code = unescape(code);
        var c = String.fromCharCode(code.charCodeAt(0) - code.length);
        for (var i = 1; i < code.length; i++) {
            c += String.fromCharCode(code.charCodeAt(i) - c.charCodeAt(i - 1));
        }
        return c;
    },
    /**
     * 设置某个对象中的单个属性
     * @param {object} obj   源对象
     * @param {string} path  字符串路径，如'a.b.c'
     * @param {string} value 要设置的值
     */
    DAO(obj, path, value) {
        if (typeof obj != "object") {
            return false;
        }
        path = path.split(".");
        var i;
        for (i = 0; i < path.length - 1; i++) {
            if (!obj[path[i]]) {
                obj[path[i]] = {};
            }
            // console.log(obj);
            obj = obj[path[i]];
        }

        if (value) {
            obj[path[i]] = value;
        } else {
            obj[path[i]] = "";
        }
    },
    isIe(version) {
        if (navigator.userAgent.indexOf("MSIE " + version + ".0") > 0) {
            return true;
        } else {
            return false;
        }
    },
    isWeiXin() {
        //@todo
        // return 1;
        var ua = window.navigator.userAgent.toLowerCase();
        if (ua.match(/MicroMessenger/i) == "micromessenger") {
            return true;
        } else {
            return false;
        }
    },
    ifHadEncode(str) {
        return (
            str &&
            !(
                str ===
                decodeURIComponent(
                    (str.replace && str.replace(/%/g, "%25")) || str
                )
            )
        );
    },

    /**
     * get current date time
     * @return {number} the milion second
     */
    now() {
        return new Date().getTime();
    },
    /**
     * isLogin description
     * @return {Boolean} [description]
     */
    isLogin() {
        return Uts.getCookie("accrosToken") || Uts.getCookie("SPAccrosToken");
    },
    /**
     * check if local or debug mode
     * @return {Boolean} [description]
     */
    isDevMode() {
        if (
            window.location.href.indexOf("http://localhost:") != 0 &&
            window.location.href.indexOf("dev=open") == -1
        ) {
            return false;
        } else {
            return true;
        }
    },
    /**
     * copy some object
     * @param  {object}   obj the object to copy
     * @param  {Function} cb  callback when copy each props
     * @return {object}       return new object
     * @example
        copyObj(obj,callbackToRunForEachProps)
     */
    copyObj(obj, cb) {
        //用于复制
        if (typeof obj != "object") {
            return obj;
        }
        var newobj = Uts.isArray(obj) ? [] : {};
        for (var attr in obj) {
            //遍历obj的每一个属性
            newobj[attr] = Uts.copyObj(obj[attr]);
            cb && cb(obj, attr);
        }
        return newobj;
    },

    back(value) {
        history.back(value);
    },

    /**
     * use for class component //目前用于类定义的组件
     * reg hook for update callback //注册hook，以便状态保持更新
     * example:  Uts.regHook(this, function(obj) {
            UserApi.addUserStateHook(function(value) {
                obj.setState(value);
            }, 'userB');
        });
     * @param  {this}       env         [description]
     * @param  {Function}   callback    [description]
     * @return {null}                   [description]
     */
    regHook: function(env, callback) {
        (function(currentObj) {
            callback && callback(currentObj);
        })(env);
    },
    href: function(url) {
        location.href = url;
    },
    fireListen: function(options) {},
    /**
     * routeToDomain description
     * @param  {string} site [description]
     * @param  {string} url  [description]
     * @return {null}      [description]
     * @example
     * Uts.routeToDomain('hms','supply/2');
     */
    routeToDomain: function(site, url) {
        let currentEnv = Uts.getEnv();
        console.log("routeToDomain", site, url, currentEnv);
        let siteConfig = {
            hms: {
                uat: "https://hms.rjmart.rj-info.com/",
                test4: "http://hms.test4.rj-info.com/",
                gray: "https://hms.gray.rjmart.cn/",
                publish: "https://hms.rjmart.cn/",
                localhost: "../hms/hms/"
            },
            whse: {
                uat: "https://whse.rjmart.rj-info.com/",
                test4: "http://whse.test4.rj-info.com/",
                gray: "https://whse.gray.rjmart.cn/",
                publish: "https://whse.rjmart.cn/",
                localhost: "/whse/"
            }
        };
        // if (currentEnv.env != "localhost") {
        Uts.href(siteConfig[site][currentEnv.env] + "index.html#" + url);
        // } else {
        //     Uts.href("../hms/hms/index.html#" + url);
        // }
    },
    getParamsFormSearch: function(search) {
        var urlDataObj = {};
        // dd = location.search;
        if (!search) {
            // alert('参数异常，请返回');
            return {};
        }
        search = search.substring(1);
        //data=123&a=1&c=2&d=3
        var ddList = search.split("&");
        for (var i = 0; i < ddList.length; i++) {
            var tmpList = ddList[i].split("=");
            urlDataObj[tmpList[0]] = decodeURIComponent(tmpList[1]);
        }
        return urlDataObj;
    }
};

function changeHeader() {
    let currentStateName = $state.name;
    let preStateName = $state.preName;
    switch (true) {
        case Uts.contain(currentStateName, "DefaultRouter"):
            break;
        case Uts.contain(currentStateName, "cart"):
            StateApi.updateStoreState("commonHeaderConfig", { isInCart: true });
            break;
        case Uts.contain(currentStateName, "supplierShop"):
            StateApi.updateStoreState("commonHeaderConfig", { isInSupp: true });
            break;
        case Uts.contain(currentStateName, "indexPage"):
            StateApi.updateStoreState("commonHeaderConfig", { navOpen: true });
            break;
        case currentStateName == "/":
            StateApi.updateStoreState("commonHeaderConfig", { navOpen: true });
            break;
        case Uts.contain(currentStateName, "searchResults"):
            StateApi.updateStoreState("commonHeaderConfig", { searchTab: 1 });
            break;
        case Uts.contain(currentStateName, "statements"):
            StateApi.updateStoreState("commonHeaderConfig", { hideHeader: 1 });
            break;
        case Uts.contain(currentStateName, "orderResults"):
            StateApi.updateStoreState("commonHeaderConfig", { hideHeader: 1 });
            break;
        case Uts.contain(currentStateName, "HelpCenter"):
            StateApi.updateStoreState("commonHeaderConfig", {
                helpCenter: "1"
            });
            break;
        case Uts.contain(currentStateName, "HelpProblems"):
            StateApi.updateStoreState("commonHeaderConfig", {
                helpCenter: "2"
            });
            break;
        case Uts.contain(currentStateName, "HelpVideo"):
            StateApi.updateStoreState("commonHeaderConfig", {
                helpCenter: "3"
            });
            break;
        case Uts.contain(currentStateName, "Login"):
            StoreApi.updateStoreState("commonHeaderConfig", {
                hideHeader: 1
                // hideFooter: 1
            });
            break;
        case Uts.contain(currentStateName, "register"):
            StoreApi.updateStoreState("commonHeaderConfig", {
                hideHeader: 1,
                isSimpleHeader: 1 //1采购人或供应商注册，2找回密码，3找回签名密码
            });
            break;
        case Uts.contain(currentStateName, "forgetpwd"):
            StoreApi.updateStoreState("commonHeaderConfig", {
                hideHeader: 1,
                isSimpleHeader: 2
            });
            break;
        case Uts.contain(currentStateName, "SignaturePwd"):
            StoreApi.updateStoreState("commonHeaderConfig", {
                hideHeader: 1,
                isSimpleHeader: 3
            });
            break;
        case Uts.contain(currentStateName, "bid"): //竞价头部
            StoreApi.updateStoreState("commonHeaderConfig", {
                // hideHeader: 1,
                // hideFooter: 1
                hideClassify: 1,
                isInBid: 1
            });
            break;
        case Uts.contain(currentStateName, "testmlogin"): //测试弹框登录
            StoreApi.updateStoreState("commonHeaderConfig", {
                hideHeader: 1,
                hideFooter: 1
            });
            break;
        default:
            // if (Uts.isTrue(StateApi.getStateValue("commonHeaderConfig"))) {
            StateApi.updateStoreState("commonHeaderConfig", "");
        // }
    }
}

Uts.initUA();

Uts.changeHeader = changeHeader;

function changeMenu() {
    let currentStateName = $state.name;
    let selectMenu = StateApi.getStoreState("hmsMenuConfig").selectedGroup;
    switch (true) {
        case Uts.contain(currentStateName, "DefaultRouter"):
            break;
        case Uts.contain(currentStateName, "indexPage"):
            selectMenu.map((item, index) => {
                selectMenu[index] = false;
            });
            StateApi.updateStoreState("hmsMenuConfig", {
                selectedGroup: selectMenu
            });
            break;
        case Uts.contain(currentStateName, "systemSet"):
            selectMenu[11] = true;
            StateApi.updateStoreState("hmsMenuConfig", {
                selectedGroup: selectMenu
            });
            break;
        default:
            selectMenu.map((item, index) => {
                selectMenu[index] = false;
            });
            StateApi.updateStoreState("commonHeaderConfig", {
                selectedGroup: selectMenu
            });
    }
}

Uts.changeMenu = changeMenu;

if (_history && _history.location) {
    Uts.$stateName = _history.location.pathname;
    Uts.$stateParams = Uts.getParamsFormSearch(_history.location.search);
    Uts.$state = _history.location.$state;
    $state.setStateName(Uts.$stateName);
    $state.setParams(Uts.$stateParams);
    $state.setState(Uts.$state);
    // changeHeader();
}

const unlisten = _history.listen((location, action) => {
    Uts.$stateName = location.pathname;
    Uts.$stateParams = Uts.getParamsFormSearch(location.search);
    Uts.$state = _history.location.$state;
    $state.setStateName(Uts.$stateName);
    $state.setParams(Uts.$stateParams);
    $state.setState(Uts.$state);
    changeHeader();
    Uts.fireListen({ type: "locationChange", action: action });
    if ($state.preName != $state.name) {
        window.scrollTo(0, 0);
    }
    // location is an object like window.location
    // console.log(action, location.pathname, location.state);
});

function setLoginInfoForOutSideSession() {
    if ($state.params.authorizationSession) {
        global.hasLogin = true;
        Uts.setCookie("accrosToken", $state.params.authorizationSession);
        Uts.setCookie("orgId", $state.params.currentOrganization);
        Uts.setCookie("refreshToken", $state.params.refreshToken);
        global.$access_token = $state.params.authorizationSession;
        let newStateList = Uts.copyObj(Uts.autoCleanStateList);
        newStateList.push("authorizationSession");
        newStateList.push("currentOrganization");
        newStateList.push("refreshToken");
        Uts.cleanState(newStateList);
    } else {
        Uts.cleanState();
    }
}

setLoginInfoForOutSideSession();

global.Uts = Uts;

Uts.overrideAjax();

export default Uts;
